package org.jsola.hr.service.impl;

import org.jsola.core.Page;
import org.jsola.core.entity.BaseDO;
import org.jsola.exception.ParamException;
import org.jsola.hr.common.ExampleKit;
import org.jsola.hr.constant.HrConstants;
import org.jsola.hr.dao.IEmpEducationDAO;
import org.jsola.hr.dto.EmpEducationAddDTO;
import org.jsola.hr.dto.EmpEducationDTO;
import org.jsola.hr.dto.EmpEducationUpdateDTO;
import org.jsola.hr.entity.EmpEducationDO;
import org.jsola.hr.query.EmpEducationQuery;
import org.jsola.hr.service.IEmpEducationService;
import org.jsola.hr.service.IEmpInfoService;
import org.jsola.hr.vo.EmpEducationListVO;
import org.jsola.hr.vo.EmpEducationMapVO;
import org.jsola.hr.vo.EmpEducationVO;
import org.jsola.user.core.TokenUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import tk.mybatis.mapper.entity.Example;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author zhr
 */
@Service("hrEmpEducationServiceImpl")
public class EmpEducationServiceImpl implements IEmpEducationService {

    @Autowired
    private IEmpEducationDAO empEducationDAO;

    @Autowired
    private IEmpInfoService empInfoService;

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public EmpEducationVO save(EmpEducationAddDTO empEducationAddDTO, TokenUser tokenUser) {
        // 转DO
        EmpEducationDO empEducationDO = empEducationAddDTO.to(EmpEducationDO.class);

        // 校验员工和公司
        checkEmpAndCompany(empEducationDO.getEmpId(), empEducationDO.getCompanyId(), tokenUser.getSiteId());
        updateEducationOrDegreeTypeByEmpEducationDO(empEducationDO, tokenUser);
        // 保存
        empEducationDO = save(empEducationDO, tokenUser.getSiteId(), tokenUser.getUserId());
        return empEducationDO.to(EmpEducationVO.class);
    }


    /**
     * 比较学历 学位创建最高学历
     *
     * @param empEducationDO 学位信息
     */
    private void updateEducationOrDegreeTypeByEmpEducationDO(EmpEducationDO empEducationDO, TokenUser tokenUser) {

        List<EmpEducationDO> empEducationDOList = selectHighestEduAndHighestDegreeByEmpIdAndCompanyId(
                empEducationDO.getEmpId(), empEducationDO.getCompanyId());
        // 最高学历
        boolean isFirstEdu = true;
        // 最高学位
        boolean isFirstDegree = true;

        // 有最高学历
        List<EmpEducationDO> highestEduList = empEducationDOList.parallelStream()
                .filter(empEducation -> null != empEducation.getIsHighestEdu() && empEducation.getIsHighestEdu())
                .collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(highestEduList)) {
            // 且最高学历不是其他
            if (empEducationDO.getEducation() != null && empEducationDO.getEducation() != 9) {
                for (EmpEducationDO educationDO : highestEduList) {
                    // 更新操作跳过自己
                    if (educationDO.getId().equals(empEducationDO.getId())) {
                        continue;
                    }
                    // 没有学历跳过
                    if (educationDO.getEducation() == null) {
                        continue;
                    }
                    if (educationDO.getEducation() == 9 || educationDO.getEducation() < empEducationDO.getEducation()) {
                        EmpEducationDO updateEducationDO = new EmpEducationDO();
                        updateEducationDO.setId(educationDO.getId());
                        updateEducationDO.setIsHighestEdu(false);
                        updateEducationDO.setIsFirstEdu(false);
                        updateByIdSelective(updateEducationDO, tokenUser.getSiteId(), tokenUser.getUserId());
                    } else {
                        isFirstEdu = false;
                    }
                }
            }
        }
        if (empEducationDO.getDegreeType() == null) {
            // 学位不输肯定不是最高学位
            isFirstDegree = false;
        } else {
            // 有最高学位
            List<EmpEducationDO> highestDegree = empEducationDOList.parallelStream()
                    .filter(educationDO -> null != educationDO.getIsHighestDegree() && educationDO.getIsHighestDegree())
                    .collect(Collectors.toList());
            if (!CollectionUtils.isEmpty(highestDegree)) {
                // 有最高学位 且最高学位不是其他
                if (empEducationDO.getDegreeType() != null && empEducationDO.getDegreeType() != 4) {
                    for (EmpEducationDO educationDO : highestDegree) {
                        // 更新操作跳过自己
                        if (educationDO.getId().equals(empEducationDO.getId())) {
                            continue;
                        }
                        // 没有学位跳过
                        if (educationDO.getDegreeType() == null) {
                            continue;
                        }
                        // 历史数据 类型是4 或历史数据 类型小于 新数据 需要修改
                        if (educationDO.getDegreeType() == 4 || educationDO.getDegreeType() < empEducationDO.getDegreeType()) {
                            EmpEducationDO updateEducationDO = new EmpEducationDO();
                            updateEducationDO.setId(educationDO.getId());
                            updateEducationDO.setIsFirstDegree(false);
                            updateEducationDO.setIsHighestDegree(false);
                            updateByIdSelective(updateEducationDO, tokenUser.getSiteId(), tokenUser.getUserId());
                        } else {
                            isFirstDegree = false;
                        }
                    }
                }
            }
        }
        empEducationDO.setIsFirstEdu(isFirstEdu);
        empEducationDO.setIsFirstDegree(isFirstDegree);
        empEducationDO.setIsHighestEdu(isFirstEdu);
        empEducationDO.setIsHighestDegree(isFirstDegree);
    }


    /**
     * 查询员工教育经历的最高学历和最高学位
     *
     * @param empId     员工Id
     * @param companyId 公司Id
     * @return 员工教育经历
     */
    private List<EmpEducationDO> selectHighestEduAndHighestDegreeByEmpIdAndCompanyId(String empId, String companyId) {
        Example example = new Example(EmpEducationDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("empId", empId)
                .andEqualTo("companyId", companyId);
        example.and()
                .orEqualTo("isHighestEdu", true)
                .orEqualTo("isHighestDegree", true);
        return empEducationDAO.selectByExample(example);
    }

    /**
     * 校验员工和公司
     *
     * @param empId     员工id
     * @param companyId 公司id
     * @param siteId    站点
     */
    private void checkEmpAndCompany(String empId, String companyId, String siteId) {
        ParamException.hasLength(empId, "员工id不能为空");
        ParamException.hasLength(companyId, "公司id不能为空");
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public int update(EmpEducationUpdateDTO empEducationUpdateDTO, TokenUser tokenUser) {
        //转DO
        EmpEducationDO empEducationDO = empEducationUpdateDTO.to(EmpEducationDO.class);
        updateEducationOrDegreeTypeByEmpEducationDO(empEducationDO, tokenUser);
        //根据主键更新，只更新非null值
        return updateByIdSelective(empEducationDO, tokenUser.getSiteId(), tokenUser.getUserId());
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public int deleteByIds(TokenUser tokenUser, String... empEducationIds) {
        return logicalDeleteByIds(tokenUser.getSiteId(), tokenUser.getUserId(), (Object[]) empEducationIds);
    }


    @Override
    public EmpEducationVO selectById(String empEducationId, String siteId) {
        EmpEducationDO empEducationDO = selectDOById(empEducationId, siteId);
        if (empEducationDO == null) {
            return null;
        }
        return empEducationDO.to(EmpEducationVO.class);
    }

    @Override
    public List<EmpEducationListVO> select(EmpEducationQuery empEducationQuery, String siteId) {
        List<EmpEducationDO> empEducationDOList = selectDO(empEducationQuery, siteId);
        if (CollectionUtils.isEmpty(empEducationDOList)) {
            return empEducationDOList == null ? null : new ArrayList<>();
        }
        return empEducationDOList.stream()
                .map(empEducationDO -> empEducationDO.to(EmpEducationListVO.class))
                .collect(Collectors.toList());
    }

    @Override
    public int selectCount(EmpEducationQuery empEducationQuery, String siteId) {
        Example example = buildExample(empEducationQuery, siteId);
        return empEducationDAO.selectCountByExample(example);
    }

    @Override
    public Page<EmpEducationListVO> selectPage(EmpEducationQuery empEducationQuery, String siteId) {
        Example example = buildExample(empEducationQuery, siteId);
        Page<EmpEducationDO> page = empEducationDAO.selectPageByExample(example,
                empEducationQuery.getPageNo(),
                empEducationQuery.getPageSize());

        return page.to(EmpEducationListVO.class);
    }

    @Override
    public EmpEducationDO selectDOById(String empEducationId, String siteId) {
        return listById(empEducationId, siteId);
    }

    @Override
    public List<EmpEducationDO> selectDO(EmpEducationQuery empEducationQuery, String siteId) {
        Example example = buildExample(empEducationQuery, siteId);
        return empEducationDAO.selectByExample(example);
    }


    /**
     * 根据查询参数，构建example
     *
     * @param empEducationQuery 查询参数
     * @param siteId            所属站点id
     * @return example
     */
    private Example buildExample(EmpEducationQuery empEducationQuery, String siteId) {
        Example example = new Example(EmpEducationDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("siteId", siteId);
        if (empEducationQuery.getEmpId() != null) {
            example.and().andLike("empId", "%" + empEducationQuery.getEmpId() + "%");
        }
        if (empEducationQuery.getGraCollege() != null) {
            example.and().andLike("graCollege", "%" + empEducationQuery.getGraCollege() + "%");
        }
        if (empEducationQuery.getIsLehramt() != null) {
            example.and().andEqualTo("isLehramt", empEducationQuery.getIsLehramt());
        }
        if (empEducationQuery.getMajor() != null) {
            example.and().andLike("major", "%" + empEducationQuery.getMajor() + "%");
        }
        if (empEducationQuery.getEducation() != null) {
            example.and().andLike("education", "%" + empEducationQuery.getEducation() + "%");
        }
        if (empEducationQuery.getTeaMethods() != null) {
            example.and().andLike("teaMethods", "%" + empEducationQuery.getTeaMethods() + "%");
        }
        if (empEducationQuery.getStartTimeStart() != null &&
                empEducationQuery.getStartTimeEnd() != null) {
            example.and().andBetween("startTime", empEducationQuery.getStartTimeStart(),
                    empEducationQuery.getStartTimeEnd());
        }
        if (empEducationQuery.getEndTimeStart() != null &&
                empEducationQuery.getEndTimeEnd() != null) {
            example.and().andBetween("endTime", empEducationQuery.getEndTimeStart(),
                    empEducationQuery.getEndTimeEnd());
        }
        if (empEducationQuery.getIsFirstEdu() != null) {
            example.and().andEqualTo("isFirstEdu", empEducationQuery.getIsFirstEdu());
        }
        if (empEducationQuery.getIsHighestEdu() != null) {
            example.and().andEqualTo("isHighestEdu", empEducationQuery.getIsHighestEdu());
        }
        if (empEducationQuery.getDegreeName() != null) {
            example.and().andEqualTo("degreeName", empEducationQuery.getDegreeName());
        }
        if (empEducationQuery.getIsFirstDegree() != null) {
            example.and().andEqualTo("isFirstDegree", empEducationQuery.getIsFirstDegree());
        }
        if (empEducationQuery.getIsHighestDegree() != null) {
            example.and().andEqualTo("isHighestDegree", empEducationQuery.getIsHighestDegree());
        }
        if (empEducationQuery.getCompanyId() != null) {
            example.and().andEqualTo("companyId", empEducationQuery.getCompanyId());
        }
        if (empEducationQuery.getGmtCreateStart() != null &&
                empEducationQuery.getGmtCreateEnd() != null) {
            example.and().andBetween("gmtCreate", empEducationQuery.getGmtCreateStart(),
                    empEducationQuery.getGmtCreateEnd());
        }
        if (empEducationQuery.getCreateUserId() != null) {
            example.and().andLike("createUserId", "%" + empEducationQuery.getCreateUserId() + "%");
        }
        if (empEducationQuery.getGmtModifiedStart() != null &&
                empEducationQuery.getGmtModifiedEnd() != null) {
            example.and().andBetween("gmtModified", empEducationQuery.getGmtModifiedStart(),
                    empEducationQuery.getGmtModifiedEnd());
        }
        if (empEducationQuery.getModifiedUserId() != null) {
            example.and().andLike("modifiedUserId", "%" + empEducationQuery.getModifiedUserId() + "%");
        }
        // 排序
        ExampleKit.setExampleOrder(example, empEducationQuery.getOrders());
        return example;
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public Integer deleteEmpEducation(TokenUser tokenUser, String empEducationId) {
        return empEducationDAO.deleteByPrimaryKey(empEducationId);
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public void deleteByCompanyId(String companyId, TokenUser tokenUser) {
        Example example = new Example(EmpEducationDO.class);
        example.and()
                .andEqualTo("companyId", companyId)
                .andEqualTo("valid", true)
                .andEqualTo("siteId", tokenUser.getSiteId());
        // 逻辑删除
        List<EmpEducationDO> list = empEducationDAO.selectByExample(example);
        String[] ids = list.stream()
                .map(BaseDO::getId).toArray(String[]::new);
        deleteByIds(tokenUser, ids);
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public void publishEmpEducationList(List<EmpEducationDTO> empEducationList, String companyId, String empId, TokenUser tokenUser) {
        // 删除某个员工所有的
        deleteByEmpId(empId, tokenUser);

        if (CollectionUtils.isEmpty(empEducationList)) {
            return;
        }

        empEducationList.forEach(
                empEducationDTO -> {
                    empEducationDTO.setCompanyId(companyId);
                    empEducationDTO.setEmpId(empId);
                    // 新增
                    EmpEducationAddDTO empEducationAddDTO = empEducationDTO.to(EmpEducationAddDTO.class);
                    save(empEducationAddDTO, tokenUser);
                }
        );
        /*// 最高学历
        int educationTop = -1;
        // 学历-其他
        final int EDUCATION_OTHER = 9;
        for (EmpEducationDTO empEducationDTO : empEducationList) {
            empEducationDTO.setCompanyId(companyId);
            empEducationDTO.setEmpId(empId);
            // 新增
            EmpEducationAddDTO empEducationAddDTO = empEducationDTO.to(EmpEducationAddDTO.class);
            save(empEducationAddDTO, tokenUser);
            // 教育学历
            Integer education = empEducationDTO.getEducation();
            if (null != education) {
                int education1 = education == EDUCATION_OTHER ? 0 : education;
                if (educationTop < education1) {
                    educationTop = education1;
                }
            }
        }

        EmpInfoUpdateDTO empInfoUpdateDTO = new EmpInfoUpdateDTO();
        empInfoUpdateDTO.setId(empId);
        *//*empInfoUpdateDTO.setHighestEducation(
                EducationLevelEnum.find(educationTop == 0 ? EDUCATION_OTHER : educationTop).getDesc());*//*
        empInfoUpdateDTO.setHighestEducation(educationTop + "");
        empInfoService.update(empInfoUpdateDTO, tokenUser);*/
    }

    /**
     * 将教育经历数值转为为字符串
     *
     * @param educationId 教育学历key
     * @return 教育学历value
     */
    @Deprecated
    private String educationToString(int educationId) {
        String educationStr = "";
        switch (educationId) {
            case 1:
                educationStr = "小学";
                break;
            case 2:
                educationStr = "初中";
                break;
            case 3:
                educationStr = "中专";
                break;
            case 4:
                educationStr = "高中";
                break;
            case 5:
                educationStr = "大专";
                break;
            case 6:
                educationStr = "本科";
                break;
            case 7:
                educationStr = "硕士";
                break;
            case 8:
                educationStr = "博士";
                break;
            case 9:
                educationStr = "其他";
                break;
            default:
                break;
        }
        return educationStr;
    }

    @Override
    public List<EmpEducationDO> listByEmpId(String empId, String siteId) {
        Example example = new Example(EmpEducationDO.class);
        example.and()
                .andEqualTo("empId", empId)
                .andEqualTo("valid", true)
                .andEqualTo("siteId", siteId);
        example.orderBy("gmtCreate");
        //
        return empEducationDAO.selectByExample(example);
    }

    @Override
    public Map<String, String> selectHighestEducationAndDegree(String empId) {
        Example example = new Example(EmpEducationDO.class);
        example.and().andEqualTo("valid", true)
                .andEqualTo("empId", empId);
        Map<String, String> highestEducationAndDegree = new HashMap<>(8);
        //查询到这个人的所有教育经历
        List<EmpEducationDO> empEducationDOList = empEducationDAO.selectByExample(example);
        //如果没有查询到此人的教育经历，直接都赋空值返回
        if (CollectionUtils.isEmpty(empEducationDOList)) {
            return assignmentNull(highestEducationAndDegree);
        }
        //取所有教育经历中学历最高的一条,过滤掉保存过教育经历,但是学历未填写的情况
        List<EmpEducationDO> empEducationDOListComparing = empEducationDOList.stream()
                .filter(empEducationDO -> empEducationDO.getEducation() != null)
                .sorted(Comparator.comparing(EmpEducationDO::getEducation).reversed())
                .collect(Collectors.toList());
        if (CollectionUtils.isEmpty(empEducationDOListComparing)) {
            empEducationDOListComparing = empEducationDOList.stream()
                    .sorted(Comparator.comparing(EmpEducationDO::getGmtCreate).reversed())
                    .collect(Collectors.toList());
        }
        //过滤完需要再次判空
        if (CollectionUtils.isEmpty(empEducationDOListComparing)) {
            return assignmentNull(highestEducationAndDegree);
        }
        parasData(highestEducationAndDegree, empEducationDOListComparing);
        return highestEducationAndDegree;
    }

    @Override
    public List<EmpEducationMapVO> listHighestEducationAndDegree(List<String> empIdList) {
        ParamException.notEmpty(empIdList, "员工id不能为空");
        Example example = new Example(EmpEducationDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andIn("empId", empIdList);
        //查询到这个人的所有教育经历
        List<EmpEducationDO> allEmpEducationDOList = empEducationDAO.selectByExample(example);
        // 根据员工id分组
        Map<String, List<EmpEducationDO>> empIdEducationMap = allEmpEducationDOList.parallelStream()
                .collect(Collectors.groupingBy(EmpEducationDO::getEmpId));
        // 员工-教育经历 列表
        List<EmpEducationMapVO> empEducationMapList = new ArrayList<>();
        new EmpEducationMapVO();
        EmpEducationMapVO empEducationMap;
        for (Map.Entry<String, List<EmpEducationDO>> entry : empIdEducationMap.entrySet()) {
            empEducationMap = new EmpEducationMapVO();
            // 员工id
            String empId = entry.getKey();
            empEducationMap.setEmpId(empId);
            // 教育经历
            List<EmpEducationDO> empEducationDOList = entry.getValue();

            Map<String, String> highestEducationAndDegree = new HashMap<>(8);
            //如果没有查询到此人的教育经历，直接都赋空值返回
            if (CollectionUtils.isEmpty(empEducationDOList)) {
                Map<String, String> empIdEduMap = assignmentNull(highestEducationAndDegree);
                empEducationMap.setEmpEducationMap(empIdEduMap);
                empEducationMapList.add(empEducationMap);
                continue;
            }
            //取所有教育经历中学历最高的一条,过滤掉保存过教育经历,但是学历未填写的情况
            List<EmpEducationDO> empEducationDOListComparing = empEducationDOList.stream()
                    .filter(empEducationDO -> empEducationDO.getEducation() != null)
                    .sorted(Comparator.comparing(EmpEducationDO::getEducation).reversed())
                    .collect(Collectors.toList());
            if (CollectionUtils.isEmpty(empEducationDOListComparing)) {
                empEducationDOListComparing = empEducationDOList.stream()
                        .sorted(Comparator.comparing(EmpEducationDO::getGmtCreate).reversed())
                        .collect(Collectors.toList());
            }
            //过滤完需要再次判空
            if (CollectionUtils.isEmpty(empEducationDOListComparing)) {
                Map<String, String> empIdEduMap = assignmentNull(highestEducationAndDegree);
                empEducationMap.setEmpEducationMap(empIdEduMap);
                empEducationMapList.add(empEducationMap);
                continue;
            }
            parasData(highestEducationAndDegree, empEducationDOListComparing);
            empEducationMap.setEmpEducationMap(highestEducationAndDegree);
            empEducationMapList.add(empEducationMap);
        }
        return empEducationMapList;
    }

    /**
     * 处理员工学历数据
     */
    private void parasData(Map<String, String> highestEducationAndDegree, List<EmpEducationDO> empEducationDOListComparing) {
        EmpEducationDO empEducationDO = empEducationDOListComparing.get(0);
        if (empEducationDOListComparing.size() > 1 && Objects.equals(empEducationDO.getEducation(), 9)) {
            empEducationDO = empEducationDOListComparing.get(1);
        }
        //赋值毕业院校
        highestEducationAndDegree.put("graCollege", empEducationDO.getGraCollege());
        //赋值毕业专业
        highestEducationAndDegree.put("major", empEducationDO.getMajor());
        //赋值学习形式
        highestEducationAndDegree.put("teaMethods", empEducationDO.getTeaMethods());
        if (empEducationDO.getEducation() == null) {
            highestEducationAndDegree.put("education", "");
        } else {
            switch (empEducationDO.getEducation()) {
                case 1:
                    highestEducationAndDegree.put("education", "小学");
                    break;
                case 2:
                    highestEducationAndDegree.put("education", "初中");
                    break;
                case 3:
                    highestEducationAndDegree.put("education", "中专");
                    break;
                case 4:
                    highestEducationAndDegree.put("education", "高中");
                    break;
                case 5:
                    highestEducationAndDegree.put("education", "大专");
                    break;
                case 6:
                    highestEducationAndDegree.put("education", "本科");
                    break;
                case 7:
                    highestEducationAndDegree.put("education", "硕士");
                    break;
                case 8:
                    highestEducationAndDegree.put("education", "博士");
                    break;
                case 9:
                    highestEducationAndDegree.put("education", "其他");
                    break;
                default:
                    highestEducationAndDegree.put("education", "");
                    break;
            }
        }
        if (empEducationDO.getDegreeType() == null) {
            highestEducationAndDegree.put("degree", "");
        } else {
            switch (empEducationDO.getDegreeType()) {
                case 1:
                    highestEducationAndDegree.put("degree", "学士");
                    break;
                case 2:
                    highestEducationAndDegree.put("degree", "硕士");
                    break;
                case 3:
                    highestEducationAndDegree.put("degree", "博士");
                    break;
                case 4:
                    highestEducationAndDegree.put("degree", "未获得学位");
                    break;
                default:
                    highestEducationAndDegree.put("degree", "");
                    break;
            }
        }
    }

    /**
     * 赋空值
     */
    private Map<String, String> assignmentNull(Map<String, String> map) {
        //学位学历赋空值
        map.put("education", "");
        map.put("degree", "");
        //毕业院校赋空值
        map.put("graCollege", "");
        //毕业专业赋空值
        map.put("major", "");
        //学习形式赋空值
        map.put("teaMethods", "");
        return map;
    }

    /**
     * 删除某个员工所有的
     *
     * @param empId     员工id
     * @param tokenUser 当前用户
     */
    private void deleteByEmpId(String empId, TokenUser tokenUser) {

        // 逻辑删除
        List<EmpEducationDO> list = listByEmpId(empId, tokenUser.getSiteId());
        String[] ids = list.stream()
                .map(BaseDO::getId).toArray(String[]::new);
        deleteByIds(tokenUser, ids);
    }
}




